﻿using System;
using NUnit.Framework;

using Rhino.Mocks;
using ValidationFramework.Reflection;
using ValidationFramework.Specifications;

namespace ValidationFramework.Specifications.Tests
{
	class IsRequiredRuleAttributeTests
	{
		[TestFixture]
		public class CreateSpecification
		{
			[Test]
			public void Should_Return_Default_Spec_If_No_Properties_Set()
			{
				// Arrange
				var attribute = new IsRequiredAttribute();
				var mockInfoDescriptor = MockRepository.GenerateMock<InfoDescriptor>(typeof(int).TypeHandle, "testMember");
				var expectedSpec = new IsRequiredSpec<int>();
				
				// Act
				var validator = attribute.CreateSpecification(mockInfoDescriptor);
				
				// Assert
				Assert.IsTrue(validator.IsEquivalentTo(expectedSpec));
			}

			[Test]
			public void Should_Infer_Generic_Type_From_InfoDescriptor()
			{
				// Arrange
				var attribute = new IsRequiredAttribute();
				var mockInfoDescriptor = MockRepository.GenerateMock<InfoDescriptor>(typeof(int).TypeHandle, "testMember");

				// Act
				var validator = attribute.CreateSpecification(mockInfoDescriptor);

				// Assert
				Assert.AreEqual(validator.GetType(), typeof(IsRequiredSpec<int>));
			}

			[Test]
			[ExpectedException(typeof(ArgumentOutOfRangeException))]
			public void Should_Throw_If_InitialValue_Type_Cannot_Be_Cast_To_Infered_Type()
			{
				// Arrange
				var attribute = new IsRequiredAttribute() { InitialValue = "something" };
				var mockInfoDescriptor = MockRepository.GenerateMock<InfoDescriptor>(typeof(int).TypeHandle, "testMember");

				// Act
				var validator = attribute.CreateSpecification(mockInfoDescriptor);

				// Assert
				Assert.AreEqual(validator.GetType(), typeof(IsRequiredSpec<int>));
			}
		}
	}
}
